package com.fengke.payment.tencent.business;

import com.fengke.payment.tencent.common.Log;
import com.fengke.payment.tencent.common.Signature;
import com.fengke.payment.tencent.common.Util;
import com.fengke.payment.tencent.protocol.unified_order_protocol.UnifiedOrderReqData;
import com.fengke.payment.tencent.protocol.unified_order_protocol.UnifiedOrderResData;
import com.fengke.payment.tencent.service.UnifiedOrderService;

import org.slf4j.LoggerFactory;

public class UnifiedOrderBusiness {

	public UnifiedOrderBusiness() throws IllegalAccessException, ClassNotFoundException, InstantiationException {
		unifiedOrderService = new UnifiedOrderService();
	}

	public interface ResultListener {

		// API返回ReturnCode不合法，支付请求逻辑错误，请仔细检测传过去的每一个参数是否合法，或是看API能否被正常访问
		void onFailByReturnCodeError(UnifiedOrderResData unifiedOrderResData);

		// API返回ReturnCode为FAIL，支付API系统返回失败，请检测Post给API的数据是否规范合法
		void onFailByReturnCodeFail(UnifiedOrderResData unifiedOrderResData);

		// 支付请求API返回的数据签名验证失败，有可能数据被篡改了
		void onFailBySignInvalid(UnifiedOrderResData unifiedOrderResData);
		
		// 商户无此接口权限
		void onFailByNoAuth(UnifiedOrderResData unifiedOrderResData);
		
		// 用户余额不足，换其他卡支付或是用现金支付
		void onFailByMoneyNotEnough(UnifiedOrderResData unifiedOrderResData);

		// 商户订单已支付，无需重复支付
		void onFailByOrderPaid(UnifiedOrderResData unifiedOrderResData);
		
		// 订单已关闭，无法支付
		void onFailByOrderClosed(UnifiedOrderResData unifiedOrderResData);
		
		// 系统错误，系统超时
		void onFailBySystemError(UnifiedOrderResData unifiedOrderResData);
		
		// 参数异常
		void onFailByParamError(UnifiedOrderResData unifiedOrderResData);
		
		// 支付失败
		void onFail(UnifiedOrderResData unifiedOrderResData);

		// 支付成功
		void onSuccess(UnifiedOrderResData unifiedOrderResData);

	}

	// 打log用
	private static Log log = new Log(LoggerFactory.getLogger(UnifiedOrderBusiness.class));

	private UnifiedOrderService unifiedOrderService;

	/**
	 * 直接执行统一下单业务逻辑（包含最佳实践流程）
	 * 
	 * @param unifiedOrderReqData
	 *            这个数据对象里面包含了API要求提交的各种数据字段
	 * @param resultListener
	 *            商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件，并做好合理的响应处理
	 * @throws Exception
	 */
	public void run(UnifiedOrderReqData unifiedOrderReqData, ResultListener resultListener) throws Exception {

		// 接受API返回
		String unifiedOrderServiceResponseString;

		long costTimeStart = System.currentTimeMillis();

		log.i("统一下单API返回的数据如下：");
		unifiedOrderServiceResponseString = unifiedOrderService.request(unifiedOrderReqData);

		long costTimeEnd = System.currentTimeMillis();
		long totalTimeCost = costTimeEnd - costTimeStart;
		log.i("统一下单api请求总耗时：" + totalTimeCost + "ms");

		// 打印回包数据
		log.i(unifiedOrderServiceResponseString);

		// 将从API返回的XML数据映射到Java对象
		UnifiedOrderResData unifiedOrderResData = (UnifiedOrderResData) Util.getObjectFromXML(unifiedOrderServiceResponseString, UnifiedOrderResData.class);

		if (unifiedOrderResData == null || unifiedOrderResData.getReturn_code() == null) {
			log.e("【统一下单接口失败】统一下单请求逻辑错误，请仔细检测传过去的每一个参数是否合法，或是看API能否被正常访问");
			resultListener.onFailByReturnCodeError(unifiedOrderResData);
			return;
		}

		if (unifiedOrderResData.getReturn_code().equals("FAIL")) {
			// 注意：一般这里返回FAIL是出现系统级参数错误，请检测Post给API的数据是否规范合法
			log.e("【统一下单失败】统一下单API系统返回失败，请检测Post给API的数据是否规范合法");
			resultListener.onFailByReturnCodeFail(unifiedOrderResData);
			return;
		} else {
			log.i("统一下单API系统成功返回数据");
			// --------------------------------------------------------------------
			// 收到API的返回数据的时候得先验证一下数据有没有被第三方篡改，确保安全
			// --------------------------------------------------------------------
			if (!Signature.checkIsSignValidFromResponseString(unifiedOrderServiceResponseString)) {
				log.e("【统一下单】支付请求API返回的数据签名验证失败，有可能数据被篡改了");
				resultListener.onFailBySignInvalid(unifiedOrderResData);
				return;
			}

			// 获取错误码
			String errorCode = unifiedOrderResData.getErr_code();
			// 获取错误描述
			String errorCodeDes = unifiedOrderResData.getErr_code_des();

			if (unifiedOrderResData.getResult_code().equals("SUCCESS")) {

				// --------------------------------------------------------------------
				// 1)统一下单成功
				// --------------------------------------------------------------------

				log.i("【统一下单成功】");
				resultListener.onSuccess(unifiedOrderResData);
			} else {
				// 出现业务错误
				log.i("统一下单-业务返回失败");
				log.i("err_code:" + errorCode);
				log.i("err_code_des:" + errorCodeDes);

				// 业务错误时错误码有好几种，商户重点提示以下几种
				if (errorCode.equals("NOAUTH") || errorCode.equals("NOTENOUGH") || errorCode.equals("ORDERPAID") || errorCode.equals("ORDERCLOSED")) {

					// --------------------------------------------------------------------
					// 2)扣款明确失败
					// --------------------------------------------------------------------

					// 以下几种情况建议明确提示用户，指导接下来的工作
					if (errorCode.equals("NOAUTH")) {
						// 商户无此接口权限，商户未开通此接口权限
						log.w("【统一下单明确失败】原因是：" + errorCodeDes);
						resultListener.onFailByNoAuth(unifiedOrderResData);
					} else if (errorCode.equals("NOTENOUGH")) {
						// 提示用户余额不足，换其他卡支付或是用现金支付
						log.w("【统一下单明确失败】原因是：" + errorCodeDes);
						resultListener.onFailByMoneyNotEnough(unifiedOrderResData);
					} else if (errorCode.equals("ORDERPAID")) {
						// 商户订单已支付，无需重复操作
						log.w("【统一下单明确失败】原因是：" + errorCodeDes);
						resultListener.onFailByOrderPaid(unifiedOrderResData);
					} else if (errorCode.equals("ORDERCLOSED")) {
						// 订单已关闭
						log.w("【统一下单明确失败】原因是：" + errorCodeDes);
						resultListener.onFailByOrderClosed(unifiedOrderResData);
					}
				} else if (errorCode.equals("SYSTEMERROR")) {
					// 系统错误，系统超时
					log.e("【统一下单明确失败】原因是：" + errorCodeDes);
					resultListener.onFailBySystemError(unifiedOrderResData);
				} else {
					// 参数异常
					log.e("【统一下单明确失败】原因是：" + errorCodeDes);
					resultListener.onFailByParamError(unifiedOrderResData);
				}
			}
		}
	}

	public void setUnifiedOrderService(UnifiedOrderService service) {
		unifiedOrderService = service;
	}

}
